package com.htu.study.service.serviceImpl.user.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Component
public class JwtUtil {
    public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14;  // 有效期14天
    public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";//长度足够长

    /*
     * 获得唯一的JWTid
     * */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
    /*
     * Java JWT（jjwt）库中的一个类，用于构建 JSON Web Token（JWT）
     * 定义一个JwtBuilder的对象builder
     * 用来接收getJwtBuilder()生成的JWT
     * builder.compact()将JwtBuilder对象转换为JWT字符串，并返回该字符串
     * */
    public static String createJWT(String subject) {
        JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
        return builder.compact();
    }
    /*
     * SignatureAlgorithm:定义 JWT 的签名算法,SignatureAlgorithm.HS256 表示使用 HMAC-SHA256 算法来进行签名
     * SecretKey:调用了 generalKey() 方法来生成一个密钥
     * nowMillis:获得当前时间的时间戳
     * ttlMillis:过期时间
     * Jwts.builder():用于创建 JWT 的构建器方法
     * setId(uuid):设置了 JWT 的唯一标识符（jti）
     * setSubject(subject):设置了 JWT 的主题（subject），通常用于表示 JWT 的所有者或者主体
     * setIssuer("sg"):设置了 JWT 的签发者（issuer），通常用于标识 JWT 的签发者
     * setIssuedAt(now):设置了 JWT 的签发时间（issued at），即 JWT 的生成时间
     * signWith(signatureAlgorithm, secretKey):设置了 JWT 的签名算法和密钥
     * setExpiration(expDate)：设置了 JWT 的过期时间
     * */
    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        SecretKey secretKey = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        return Jwts.builder()
                .setId(uuid)
                .setSubject(subject)
                .setIssuer("sg")
                .setIssuedAt(now)
                .signWith(signatureAlgorithm, secretKey)
                .setExpiration(expDate);
    }
    /*
     * generalKey():生成对称密钥
     * Base64.getDecoder().decode():Base64编码的密钥字符串解码为字节数组
     * SecretKeySpec():解码后的字节数组 encodeKey 来创建一个新的 SecretKeySpec 对象,使用 HmacSHA256 算法来进行签名和验证
     * */
    public static SecretKey generalKey() {
        byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
    }
    /*
     * Claims parseJWT:解析JWT字符串,并可以通过Claims中的方法来访问和操作 JWT 中的声明信息
     * Jwts.parserBuilder().setSigningKey(secretKey).build():使用 Java JWT 库中的 Jwts.parserBuilder() 方法创建一个 JWT 解析器（parser），
     * 并设置用于验证签名的密钥为上一步获取的对称密钥 secretKey。
     * parseClaimsJws(jwt):行解析和验证jwt,返回一个 Jws 对象，其中包含了 JWT 的头部、载荷和签名信息
     * getBody():获取 JWT 的声明（claims），并将其作为方法的返回值返回
     * */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey secretKey = generalKey();
        return Jwts.parserBuilder()
                .setSigningKey(secretKey)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }
}
